xlv.sys={
	zIndexFrame:1000,
	zIndexDock:2000,
	zIndexModal:3000,
	zIndexEffect:4000,
	zIndexDnd:5000,
	zIndexPopup:6000,
	zIndexSystemModal:7000,
	xSessionId:null,
	newObject:function(name,prop,method,tag){
		try{
			var obj=xlv.obj[name].create(tag);
			$(obj);
			xlv.sys.extend(obj,prop,method);
			return obj;
		}catch(e){alert('newObject error :'+name+'\n'+e);}
	},
	newInstance:function(parent,name,prop,method,beforeSibling,tag){
		var obj=xlv.sys.newObject(name,prop,method,tag);
		parent.insertBefore(obj,(beforeSibling)?beforeSibling:null);
		xlv.sys.initialize(obj);
		return obj;
	},
	shell:function(element,prop,method){
		$(element);
		xlv.sys.extend(element,prop,method);
		xlv.sys.initialize(element);
	},
	extend:function(element,prop,method){
		var log=[];
		try{
			var xvc=element.getAttribute('xlvobject');
			if(xvc){
				if(element._$extended)return;
				Object.extend(element,xlv.object);
				element.extend(xvc);
				var objs=element.getObjects();
				for(var i=0,n=objs.length;i<n;++i) xlv.sys.extend(objs[i]);
				if(prop)Object.extend(element.properties,(prop.evalJSON)?prop.evalJSON():new Object(prop));
				if(method)Object.extend(element,(method.evalJSON)?method.evalJSON():new Object(method));
				element._$extended=true;
				if(!element._$constructed) element.construct();
				element._$constructed=true;
			}
		}catch(e){alert('extend function call\nxlv: '+element.xlvobject+' id: '+element.id+'\nexception: '+e);}
	},
	_clearExtendedFlag:function(element){
		var objs=xlv.util.descendants(element,{xlvobject:'*'});
		for(var i=0;i<objs.length;++i){
			objs[i]._$extended=false;
			objs[i]._$constructed=false;
			objs[i]._$exts=null;
			objs[i]._$imps=null;
			objs[i]._$initialized=false;
		}
	},
	_patchIEProperties:function(element){//IE fix for pattern tag
		var objs=xlv.util.descendants(element,{xlvobject:'*'});
		objs.unshift(element);
		for(var s=0;s<objs.length;++s){
			var obj=objs[s];
		  	for(var property in obj) {
				if('properties'==property||property.endsWith('_properties')){
					obj[property]=Object.toJSON(obj[property]).evalJSON();
				}
				if('properties'==property){
					obj.properties._$var={};
					obj.$V=obj.properties._$var;
					obj.$P=obj.properties;
				}
		  	}
		}
		return element;
	},
	clonePatternNode:function(element){
		var target=element.cloneNode(true);
		if(Prototype.Browser.IE) return xlv.sys._patchIEProperties(target);
		var es=xlv.util.descendants(element,{xlvobject:'*'});
		var ts=xlv.util.descendants(target,{xlvobject:'*'});
		for(var i=0;i<es.length;++i){
			xlv.sys._cloneField(ts[i],es[i]);
			ts[i]._$constructed=true;
		}
		xlv.sys._cloneField(target,element);
		target._$constructed=true;
		return target;
	},
	_cloneField:function(target, element){
	  	for(var field in element) {
	    	if(Object.isUndefined(target[field])) {
	    		if(Object.isFunction(element[field]))target[field]=element[field];
	    		else {
	    			target[field]=element[field];
					if('properties'==field||field.endsWith('_properties')){
						target[field]=Object.toJSON(element[field]).evalJSON();
					}
					if('properties'==field){
						target.properties._$var={};
						target.$V=target.properties._$var;
						target.$P=target.properties;
					}
	    		}
			}
	  	}
	},
	initialize:function(element){
		var dm=[],mvc=[];
		if(element.parentNode||element==document.body){
			xlv.sys._initial(element,dm,mvc);
			for(var d=0;d<dm.length;++d) {
				var dm_dmc=xlv.util.locateImplement(dm[d],'xlv.imp.dmc');
				if(dm_dmc) dm[d]=dm_dmc.dmc_dmRegister(dm[d]);
			}
			for(var i=0;i<mvc.length;++i) mvc[i].mvc_addListener();
			for(var m=dm.length-1;m>=0;--m)	if(dm[m].isStarted())dm.splice(m,1);
			if(dm.length>0&&element['isExtend']&&(element.isExtend('xlv.obj.pane')||element.isExtend('xlv.obj.borderLayout'))){
				this._dmReadyMonitor(element,dm);
			}
			xlv.desktop.dmc_dmStart();
		}else{
			alert('element cannot initialize : must have a parent :'+element.tagName);
		}
	},
	_initial:function(element,dm,mvc){
		if(element._$initialized)return;
		element._$initialized=true;
		if(element['initial'])element.initial();
		if(element['isExtend']&&element.isExtend('xlv.obj.dm')) dm.push(element);
		if(element['mvc_properties']) mvc.push(element);
		var objs=xlv.util.getObjects(element);
		for(var i=0,n=objs.length;i<n;++i) xlv.sys._initial(objs[i],dm,mvc);
		if(element.startObserve) element.startObserve();
	},
	_dmReadyMonitor:function(pane,dms){
		if(dms.length>0){
			pane.$V.__dmReady_dms=dms;
			pane.__dm_ready=function(event){
				event.stop();
				var tdm=event.target;
				for(var i=pane.$V.__dmReady_dms.length-1;i>=0;--i){
					var pdm=pane.$V.__dmReady_dms[i];
					if(pdm==tdm||(pdm.$P.globe&&tdm.$P.globe&&pdm.$P.name==tdm.$P.name)){
						pane.$V.__dmReady_dms.splice(i,1);
						break;
					}
				}
				if(pane.$V.__dmReady_dms.length==0){
					pane.removeObserve('xlv:dm_ready','__dm_ready',pane);
					pane.__dm_ready=null;
					pane.$V.__dmReady_dms=null;
					var memo=xlv.sys.createMemoObject({type:'dm_ready',src:pane,from:pane,to:pane});
					pane.queueTimeout((function(){Event.fire(pane,'xlv:pane_dm_ready',memo);}).bind(pane));
				}
			};
			pane.addEventHandler('xlv:dm_ready','__dm_ready',pane);
		}
	},
	disposable:function(element){
		var objs=xlv.util.getObjects(element);
		var ret=[];
		for(var i=0,n=objs.length;i<n;++i)	ret=ret.concat(xlv.sys.disposable(objs[i]));
		if(element.disposable && !element.disposable()) ret.push(element); 
		return ret;
	},
	dispose:function(element,remove){
		if(element.stopObserve)element.stopObserve();
		var objs=xlv.util.getObjects(element);
		for(var i=0,n=objs.length;i<n;++i)	xlv.sys.dispose(objs[i]);
		if(element['mvc_properties']) element.mvc_removeListener();
		if(element['isExtend'] && element.isExtend('xlv.obj.dm')){
			var dm_dmc=xlv.util.locateImplement(element,'xlv.imp.dmc');
			dm_dmc.dmc_dmUnregister(element);
		}
		if(element['isExtend'] && !element.isExtend('xlv.obj.frame') && !element.isExtend('xlv.obj.pane')){
			if(element['dispose'])element['dispose']();
		}
		if(remove && element.parentNode) element.parentNode.removeChild(element);
	},
	broadcast:function(element,options){
		options=Object.extend({when:'before',childOnly:false,methodName:null,params:null},(options||{}));
		if(options.when=='before'&&element[options.methodName]) element[options.methodName](options.params);
		var objs=xlv.util.getObjects(element);
		for(var i=0,n=objs.length;i<n;++i) {
			if(options.childOnly) {
				if((objs[i])[options.methodName])(objs[i])[options.methodName](options.params);
			}
			else xlv.sys.broadcast(objs[i],options);
		}
		if(options.when=='after'&&element[options.methodName]) element[options.methodName](options.params);
	},
	broadcastMessage:function(element,memo){
		if(!element||!memo)return;
		if(element.message){
			element.message(memo);
			if(memo.cancelable&&memo.cancel)return;
		}
		var objs=xlv.util.getObjects(element);
		for(var i=0,n=objs.length;i<n;++i) xlv.sys.broadcastMessage(objs[i],memo);
	},
	createMemoObject:function(memo){
		return Object.extend({type:null,methods:null,src:null,from:null,to:null,cancel:false,cancelable:true,value:null,returnValue:''},
				memo||{});
	},
	pauseObserve:function(element){
		xlv.sys.broadcast(element,{when:'after',functionName:'pauseObserve'});
	},
	restoreObserve:function(element){
		xlv.sys.broadcast(element,{when:'after',functionName:'restoreObserve'});
	},
	_registerCurrentEditor:function(editor){
		xlv.sys._currentEditor=(editor&&editor['isImplement']&&editor.isImplement('xlv.imp.editor'))?editor:null;
	},
	getCurrentEditor:function(){
		var ed=xlv.sys._currentEditor;
		return (ed&&xlv.util.isDescendantOf(ed,document.body))? ed:null;
	},
	stopCurrentEditor:function(commit){
		var ed=xlv.sys.getCurrentEditor();
		if(ed){
			ed._editor_endEdit(commit);
			xlv.sys._currentEditor=null;
		}
	},
	logMessage:function(message){
		var frame=xlv.desktop.getFrame('debug_frame.html');
		if(frame)frame.postMessage(message);
	}
};
